# BSD3.0
# cili@163.com

from http.server import HTTPServer, SimpleHTTPRequestHandler
import json
import logging
import threading
import os
file_cache = {}
projects={}


def guess_type(filename):
    """根据文件名猜测MIME类型"""
    ext = os.path.splitext(filename)[1].lower()
    return extensions_map.get(ext, extensions_map[''])

# 添加支持的文件类型
extensions_map = {
    '': 'application/octet-stream',
    '.html': 'text/html',
    '.htm': 'text/html',
    '.js': 'application/javascript',
    '.css': 'text/css',
    '.json': 'application/json',
    '.png': 'image/png',
    '.jpg': 'image/jpeg',
    '.jpeg': 'image/jpeg',
    '.gif': 'image/gif',
    '.svg': 'image/svg+xml',
    '.ico': 'image/x-icon',
    '.txt': 'text/plain',
    '.md': 'text/markdown',
    '.woff': 'font/woff',
    '.woff2': 'font/woff2',
    '.ttf': 'font/ttf',
    '.eot': 'application/vnd.ms-fontobject',
    '.otf': 'font/otf',
    '.xml': 'application/xml',
}

def preload_static_files():
    """预加载静态文件到内存"""
    static_files = [
        'login.html',
        'mdeditor.html'
    ]
    static_dirs = ['js', 'css', 'editor.md']

    for file_name in static_files:
        if os.path.exists(file_name):
            with open(file_name, 'rb') as f:
                file_cache[f'/{file_name}'] = {
                    'content': f.read(),
                    'content_type': guess_type(file_name)
                }

    for dir_name in static_dirs:
        if not os.path.exists(dir_name):
            continue
        for root, _, files in os.walk(dir_name):
            for file in files:
                full_path = os.path.join(root, file)
                web_path = '/' + full_path.replace('\\', '/')
                with open(full_path, 'rb') as f:
                    file_cache[web_path] = {
                        'content': f.read(),
                        'content_type': guess_type(file)
                    }
preload_static_files()

class CustomHTTPHandler(SimpleHTTPRequestHandler):


    def do_GET(self):
        # 添加对敏感文件的保护
        sensitive_files = ['mdproject/projects.json', 'projects.json']
        requested_path = self.translate_path(self.path).replace('\\', '/')
        if any(sensitive_file in requested_path for sensitive_file in sensitive_files):
            self.send_error(403, "Access Forbidden")
            return
        
        if self.path == '/' or self.path == '/index.html':
            self.path = '/login.html'
        elif self.path == '/api/projects':
            self.send_response(200)
            self.send_header('Content-Type', 'application/json')
            self.send_header('Access-Control-Allow-Origin', '*')
            self.end_headers()
            with open('mdproject/projects.json','r',encoding='utf-8') as f:
                self.projects = json.load(f)
            t= list(self.projects)
            print(t)
            self.wfile.write(json.dumps({
                'success': True,
                'projects': t
            }).encode('utf-8'))
            return

        # 从缓存获取静态文件
        if self.path in file_cache and False:
            cached_file = file_cache[self.path]
            self.send_response(200)
            self.send_header('Content-Type', cached_file['content_type'])
            self.send_header('Content-Length', str(len(cached_file['content'])))
            self.send_header('Access-Control-Allow-Origin', '*')
            # 对静态资源添加缓存控制
            self.send_header('Cache-Control', 'public, max-age=3600')
            self.end_headers()
            self.wfile.write(cached_file['content'])
            return
            
        # 处理非缓存文件
        try:
            # 获取文件路径
            file_path = self.translate_path(self.path)

            # 检查文件是否存在
            if not os.path.exists(file_path):
                self.send_error(404, f"File not found: {self.path}")
                return

            # 获取文件大小
            file_size = os.path.getsize(file_path)
            if file_size == 0:
                self.send_error(404, f"Empty file: {self.path}")
                return

            # 禁用缓存
            self.send_response(200)
            self.send_header('Cache-Control', 'no-cache, no-store, must-revalidate')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Expires', '0')
            self.send_header('Access-Control-Allow-Origin', '*')
            self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
            self.send_header('Access-Control-Allow-Headers', 'Content-Type')

            # 设置正确的 Content-Type
            content_type = self.guess_type(self.path)
            if content_type.startswith(('text/', 'application/javascript', 'application/json')):
                self.send_header('Content-Type', f'{content_type}; charset=utf-8')
            else:
                self.send_header('Content-Type', content_type)

            # 设置 Content-Length
            self.send_header('Content-Length', str(file_size))
            self.end_headers()

            # 读取并发送文件内容
            with open(file_path, 'rb') as f:
                self.copyfile(f, self.wfile)

        except Exception as e:
            logging.error(f"HTTP Server error: {e}")
            self.send_error(500, f"Internal server error: {str(e)}")

    def do_POST(self):
        try:
            if self.path == '/api/join':
                with open('mdproject/projects.json', 'r', encoding='utf-8') as f:
                    self.projects = json.load(f)
                content_length = int(self.headers['Content-Length'])
                post_data = self.rfile.read(content_length)
                data = json.loads(post_data.decode('utf-8'))

                project = data.get('project')
                password = data.get('password')

                if (project in self.projects and self.projects[project] == password):
                    response = {
                        'success': True,
                        'message': '登录成功'
                    }
                else:
                    response = {
                        'success': False,
                        'message': '项目名或密码错误'
                    }

                self.send_response(200)
                self.send_header('Content-Type', 'application/json')
                self.send_header('Access-Control-Allow-Origin', '*')
                self.end_headers()
                self.wfile.write(json.dumps(response).encode('utf-8'))
                return
                
                

        except Exception as e:
            logging.error(f"Error processing POST request: {e}")
            self.send_error(500, f"Internal server error: {str(e)}")

    def do_OPTIONS(self):
        self.send_response(200)
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
        self.send_header('Access-Control-Allow-Headers', 'Content-Type, X-Project')
        self.end_headers()


class WebServer:
    def __init__(self, port=8080):
        self.port = port
        self.server = None
        self.thread = None

    def start(self):
        self.server = HTTPServer(('0.0.0.0', self.port), CustomHTTPHandler)
        self.thread = threading.Thread(target=self.server.serve_forever)
        self.thread.daemon = True
        self.thread.start()

    def stop(self):
        if self.server:
            self.server.shutdown()
            self.server.server_close()
